#include <xp/bas/stdio.h>
#include <xpp/Hashable.h>
#include <xpp/bas/HashList.h>

#ifdef __linux
#include <mcheck.h>
#endif

using namespace xpp;
using namespace xpp::bas;

class Int: public Hashable
{
public:
	Int (int i = 0): value (i) {}
	Int (int i, int e): value (i), extra (e) {}
	
	xp_size_t hashCode () const
	{
		return Hashable::hashCode (&value, xp_sizeof(value));
		/*return (xp_size_t)value;*/
	}

	bool operator== (const Int& i) const 
	{
		return value == i.value;
	}

	int value;
	int extra;
};

class IntHashList: public HashList<Int>
{
public:
	IntHashList (int x, int y, int mpbsz = 0): HashList<Int> (x, y, mpbsz) {}
	int print_datum_forward (Node* start, Node* cur)
	{
		Int& t = cur->value;
		xp_printf (XP_TEXT("%d, %d\n"), t.value, t.extra);
		return 1;
	}
};

extern "C" { int xp_main (); }

int xp_main ()
{
#ifdef __linux
	mtrace ();
#endif

	IntHashList list (3, 75, 100);

	list.set (Int(100, 1));
	list.set (Int(200, 2));
	list.set (Int(300, 3));
	list.set (Int(400, 4));
	list.set (Int(500, 14));
	list.set (Int(600, 24));
	list.set (Int(700, 34));
	list.set (Int(800, 44));
	list.set (Int(900, 54));
	list.set (Int(111, 64));
	list.set (Int(222, 74));
	list.remove (Int(100));
	list.remove (Int(400));

	xp_printf (XP_TEXT("%d\n"), list.valueOf(Int(300))->extra);
	xp_printf (XP_TEXT("%d\n"), list.valueOf(Int(900))->extra);

	list.set (Int(100, 789));
	xp_printf (XP_TEXT("%d\n"), list.valueOf(Int(100))->extra);

	xp_printf (XP_TEXT("-------------\n"));
	list.traverse ((IntHashList::TraverseCallback)
		&IntHashList::print_datum_forward, list.head());

	xp_printf (XP_TEXT("size=%u,capacity=%u\n"), list.size(), list.capacity());

	//IntHashList list2 (1, 1, 100);// (list);
	//list2 = list;
	IntHashList list2 (list);

	list.clear ();
	xp_printf (XP_TEXT("size=%u,capacity=%u\n"), list.size(), list.capacity());
	xp_printf (XP_TEXT("-------------\n"));

	list2.traverse ((IntHashList::TraverseCallback)
		&IntHashList::print_datum_forward, list2.head());

	return 0;
}
